#include "QtOpenCvServer.h"
#include <QMessageBox>


QtOpenCvServer::QtOpenCvServer(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint);//隐藏标题栏
    server = new QTcpServer(this);
    //判断日志文件执行操作                   
    QDate currentDate = QDate::currentDate();
    if (!QFile::exists(QString("log/%1-%2-%3.csv").arg(currentDate.year(), currentDate.month(), currentDate.day()))) {
        // 创建文件
        QFile file(QString("log/%1-%2-%3.csv").arg(currentDate.year(), currentDate.month(), currentDate.day()));
        file.open(QIODevice::WriteOnly | QIODevice::Text);
        // 创建文本流
        QTextStream TextStream(&file);
        // 在文件中插入数据
        TextStream << "ID,员工姓名,员工部门,员工职务,签到时间\n";
        file.close();
    }
    //当客户端连接时触发
    connect(server, &QTcpServer::newConnection, this, &QtOpenCvServer::onNewConnection);
}

QtOpenCvServer::~QtOpenCvServer()
{}
void QtOpenCvServer::on_addEmployees_clicked() {//
    emite:addEmployee();
}
void QtOpenCvServer::onReadyRead(QTcpSocket* clientSocket){//接收数据做进一步处理
    if(clientSocket->bytesAvailable()>0){
        //ui.logBox->append(QString("-%1:%2传输了信息").arg(clientSocket->peerAddress().toString()).arg(clientSocket->peerPort()));
        //接收图片数据
        QImage faceImage;
        QByteArray data = clientSocket->readAll();
        if (faceImage.loadFromData(data)) { // 从QByteArray加载图像数据
            // 加载成功
            cv::Mat testedFace(faceImage.height(), faceImage.width(), CV_8UC1, faceImage.bits(), faceImage.bytesPerLine());
            imshow("testedFaceData", testedFace);
            // 图像加载成功，可以进行后续处理
            QString data = QtOpenCvServer::matchingFace(testedFace);
            if (data.isEmpty())return;
            QByteArray data1 = data.toUtf8();
            if (data1.isEmpty())return;
            clientSocket->write(data1);
        }else {
            qDebug() << data;
        }   
    }
}
QString QtOpenCvServer::matchingFace(cv::Mat testedFaceData) {//从数据库匹配人脸
    //开启数据库
    QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");
    database.setDatabaseName("EmployeeIdentificationForm/EmployeeIdentificationForm.db"); // 设置数据库文件名
    if (!database.open()) {
        ui.logBox->append("数据库打开失败,无法匹配人脸");
        qDebug() << database.lastError();
        return QString();
    }
    QSqlQuery query(database);
    query.exec("SELECT * FROM employeeIdentificationForm;");
    while(query.next()) {
        //定义数据
        int ID= query.value(1).toInt();
        QString namequery = query.value(3).toString(), areaquery = query.value(2).toString(), positionquery = query.value(4).toString();
        for (int i = 5;i <= 14;i++) {
            //接收图片数据
            cv::Mat faceData = cv::imread(query.value(i).toString().toStdString());
            if (faceData.empty())break;
            imshow("faceData", faceData);
            // 图像加载成功，可以进行后续处理
            try {//获取验证人脸与被验人脸特征点
                std::vector<cv::KeyPoint> keypoints;//储存特征点
                cv::Ptr<cv::ORB> orb = cv::ORB::create();
                orb->detectAndCompute(faceData, cv::noArray(), keypoints, descriptors);
                orb->detectAndCompute(testedFaceData, cv::noArray(), keypoints, testeddescriptors);
                //通过描述子验证人脸
                cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
                std::vector<std::vector<cv::DMatch>> matches;
                matcher->knnMatch(testeddescriptors, descriptors, matches, 2);
                //筛选有效人脸特征点
                int i=QtOpenCvServer::ratioTest(matches).size();
                if (i >= 10){
                    QString dateTime = QDateTime::currentDateTime().toString();
                    //有效点大于10,人脸匹配成功
                    ui.logBox->append(QString("签到成功%1,员工:%2,工号:%3,工区和职务:%4-%5").arg(dateTime, namequery, QString::number(ID), areaquery, positionquery));
                    database.close();
                    //打开当天签到日志------------------------------------------------------------------
                    QDate currentDate = QDate::currentDate();
                    QFile logFile(QString("log/%1-%2-%3.csv").arg(currentDate.year(), currentDate.month(), currentDate.day()));
                    if (!logFile.open(QIODevice::Append | QIODevice::Text)) {
                        qDebug() << "log签到日志文件打开失败:" << logFile.errorString();
                    }
                    QTextStream logStream(&logFile);
                    logStream << ID<<","<<namequery<<","<< areaquery <<"," << positionquery<<","<< dateTime <<"\n";
                    logFile.close();
                    qDebug() << QString("%1\\%2\\%3").arg(namequery, QString::number(ID), areaquery + "-" + positionquery);
                    return QString("%1\\%2\\%3").arg(namequery, QString::number(ID), areaquery + "-" + positionquery);
                }

            }
            catch (cv::Exception e) {
                QMessageBox::information(this, "错误人脸识别", e.what());
            }
        }
    }
    database.close();
    return QString();
}
// 比率测试函数，用于筛选好的匹配点
vector<DMatch> QtOpenCvServer::ratioTest(std::vector<std::vector<cv::DMatch>>& knn_matches) {
    // 应用比率测试来筛选好的匹配
    const float ratio_thresh = 0.75; // 比率阈值
    vector<DMatch> good_matches;
    for (size_t i = 0; i < knn_matches.size(); i++) {
        if (knn_matches[i][0].distance < ratio_thresh * knn_matches[i][1].distance) {
            good_matches.push_back(knn_matches[i][0]);
        }
    }
    return good_matches;
}
void QtOpenCvServer::onNewConnection() {//客户端连接处理
    QTcpSocket* clientSocket = server->nextPendingConnection();
    qDebug() << clientSocket->readAll();
    ui.logBox->append(QString("-%1:%2已连接").arg(clientSocket->peerAddress().toString()).arg(clientSocket->peerPort()));
    // 连接readyRead信号，以便读取客户端发送的数据
    connect(clientSocket, &QTcpSocket::readyRead, this, [clientSocket, this]() {QtOpenCvServer::onReadyRead(clientSocket);});
    // 连接disconnected信号，以便在客户端断开连接时进行处理
    connect(clientSocket, &QTcpSocket::disconnected, clientSocket, [clientSocket,this] (){QtOpenCvServer::deleteLater(clientSocket);});
    //delete clientSocket;//
}
void QtOpenCvServer::deleteLater(QTcpSocket* clientSocket) {//断连反馈
    try {
        ui.logBox->append(QString("-%1:%2断开连接").arg(clientSocket->peerAddress().toString()).arg(clientSocket->peerPort()));
    }
    catch (Exception e) {
        qDebug() << e.what();
    }
    //clientSocket = nullptr;
}
//界面组件--------------------------------------
void QtOpenCvServer::on_openServer_clicked() {//建立服务器连接
    server->listen(QHostAddress::Any, 4573);//接收任意ip地址4573端口
    ui.logBox->append("-连接ing:服务器正在启动连接\n");
}
void QtOpenCvServer::on_quitApp_clicked() {//关闭按钮
    close();
}
//窗口重构--------------------------------------------
//鼠标拖拽动作v
void QtOpenCvServer::mousePressEvent(QMouseEvent* event) {
    if (event->button() == Qt::LeftButton) {
        // 记录鼠标点击时的屏幕坐标
        dragPosition = event->globalPosition() - frameGeometry().topLeft();
        // 记录拖拽状态
        isDragging = true;
    }
    else {
        // 确保只有左键按下时才进入拖拽状态
        isDragging = false;
    }
}

void QtOpenCvServer::mouseMoveEvent(QMouseEvent* event) {
    if (isDragging && (event->buttons() & Qt::LeftButton)) {
        // 更新窗口位置
        move(event->globalPosition().toPoint() - dragPosition.toPoint());
    }
}

void QtOpenCvServer::mouseReleaseEvent(QMouseEvent* event) {
    if (event->button() == Qt::LeftButton) {
        // 鼠标左键释放，结束拖拽
        isDragging = false;
    }
}